        SUBT    > Sources.OSFile - Whole file operations

 [ Version >= 176
 ; remove earlier version conditionals to ease maintenance
 ]

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; +                                                                           +
; +                             F I L E    S W I                              +
; +                                                                           +
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; FileEntry. Vectored SWI level entry
; =========
;
; Corresponds to BBC OSFile. Use temporary Filing System (generally current)

; In    r0b   =  OSFile type
;       r1    -> space or CtrlChar terminated filename. Will be translated
;       r2-r5 =  parms for OSFile

;   &FF Load file using File$Path
;     0 Save file
;     1 Write cat info
;     2 Write load addr
;     3 Write exec addr
;     4 Write attributes
;     5 Read cat info using File$Path
;     6 Delete object
;     7 Create file
;     8 Create directory
;     9 DateStamp file
;    10 Save file setting DateStamp
;    11 Create file setting DateStamp
;    12 Load file using path string
;    13 Read cat info using path string
;    14 Load file using path variable
;    15 Read cat info using path variable
;    16 Load file, no path
;    17 Read cat info, no path
;    18 Set file type
;    19 Create error from object type + name
;    20 ReadWithType
;    21 ReadWithTypePath
;    22 ReadWithTypePathVar
;    23 ReadWithTypeNoPath
 [ Version >= 176
;    24 ReadBlockSize
 ]

; Out   VC : r1 preserved
;            Load and ReadInfo ops return
;              r0 object type, r2-r5 cat info
;            Delete returns
;              r0 object type, r2-r5 cat info (file info before deletion)
;            All other ops preserve registers
;       VS : fail

FileEntry NewSwiEntry "r0-r5, r6-r10" ; Results poked into stack; was r0-r5, r6

 [ debugosfileentry
 DREG r0,"OSFile: rc ",cc
 TEQ r0, #OSFile_ReadInfo
 TEQ r0, #OSFile_Delete
 TEQNE r0, #OSFile_SetStamp
 BEQ %FT9901
 TEQ r0, #OSFile_SaveStamp ; only r4,r5 relevant
 TEQNE r0, #OSFile_CreateStamp
 BEQ %FT9900
 DREG r2," r2 ",cc
 TEQ r0, #OSFile_SetType ; only r2
 BEQ %FT9901
 DREG r3," r3 ",cc
 TEQ r0, #OSFile_Load ; only r2,r3
 TEQNE r0, #OSFile_CreateDir
 BEQ %FT9901
9900
 DREG r4," r4 ",cc
 DREG r5," r5 ",cc
9901
 DSTRING r1,": filename "
 ]

        ; Clear off any silly bits
        BIC     r0, r0, #&ffffff00

        ; Do OSFile_Load explicitly as it's out of sequence
        CMP     r0, #OSFile_Load
        BEQ     Load_UseLoadPath

  [ debugosfile
        MOV     r6, #-177               ; Bad address in r6 to cause address extinctions
  ]

        ; Check the range of the other OSFiles
        CMP     r0, #OSFile_ReadBlockSize
        JTAB    r0, LS, OSFile
        B       OSFile_BadOp
                                        ; Check values against &.Hdr.File

        JTE     SaveFileOp,             OSFile_Save;
        JTE     WriteInfoFileOp,        OSFile_WriteInfo;
        JTE     WriteInfoFileOp,        OSFile_WriteLoad;
        JTE     WriteInfoFileOp,        OSFile_WriteExec;
        JTE     WriteInfoFileOp,        OSFile_WriteAttr;
        JTE     Read_UseLoadPath,       OSFile_ReadInfo;
        JTE     DeleteCreateFileOp,     OSFile_Delete;
        JTE     DeleteCreateFileOp,     OSFile_Create;
        JTE     DeleteCreateFileOp,     OSFile_CreateDir;
        JTE     StampSetTypeFileOp,     OSFile_SetStamp;
        JTE     SaveCreateStampFileOp,  OSFile_SaveStamp;
        JTE     SaveCreateStampFileOp,  OSFile_CreateStamp;
        JTE     Load_UseGivenLoadPath,  OSFile_LoadPath
        JTE     Read_UseGivenLoadPath,  OSFile_ReadPath;
        JTE     Load_UseGivenLoadPathVar, OSFile_LoadPathVar
        JTE     Read_UseGivenLoadPathVar, OSFile_ReadPathVar;
        JTE     Load_UseNoLoadPath,     OSFile_LoadNoPath
        JTE     Read_UseNoLoadPath,     OSFile_ReadNoPath;
        JTE     StampSetTypeFileOp,     OSFile_SetType;
        JTE     MakeErrorOp,            OSFile_MakeError
        JTE     Read_UseLoadPath,       OSFile_ReadWithType
        JTE     Read_UseGivenLoadPath,  OSFile_ReadWithTypePath
        JTE     Read_UseGivenLoadPathVar, OSFile_ReadWithTypePathVar
        JTE     Read_UseNoLoadPath,     OSFile_ReadWithTypeNoPath
 [ Version >= 176
        JTE     Read_BlockSize,         OSFile_ReadBlockSize
 ]

OSFile_BadOp
        addr    r0, ErrorBlock_BadOSFileReason
        BL      CopyError
        SwiExit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; All the various ReadInfo ops

Read_UseNoLoadPath ; Try to read cat info of this file

        addr    r4, anull               ; Null path string

Read_UseGivenLoadPath ; Try to read cat info along given path string

        MOV     r2, #NULL
        MOV     r3, r4
        B       DoneTheRead


Read_UseGivenLoadPathVar ; Try to read cat info along given path variable

        MOV     r2, r4
        addr    r3, anull
        B       DoneTheRead


Read_UseLoadPath ; Try to read cat info along File$Path

        addr    r2, FilePathVariableNameCR
        ADD     r3, r2, #(FilePathVariableDefault - FilePathVariableNameCR)

; .............................................................................
; In    PassedFilename allocated
;       FullFilename and SpecialField allocated if no error and object exists

DoneTheRead
        ADR     r0, PassedFilename
        TEQ     r3, #NULL
        addr    r3, anull, EQ
        ADR     r4, FullFilename
        MOV     r5, #0
        ADR     r6, SpecialField
        BL      TopPath_DoBusinessToPath
        SwiExit VS

        ; If not doing a filetype style read then just store the results
        LDRB    r6, [fp, #0*4]
        TEQ     r6, #OSFile_ReadWithType
        TEQNE   r6, #OSFile_ReadWithTypePath
        TEQNE   r6, #OSFile_ReadWithTypePathVar
        TEQNE   r6, #OSFile_ReadWithTypeNoPath
        BNE     UpdatingJunkStringsOSFileExit

        ; Convert to filetype and store type for return
        MOV     r6, r0
        MOV     r0, r2
        BL      InfoToFileType
        Swap    r6, r2
        Swap    r2, r0
        CMP     r6, #-1
        ANDNE   r2, r2, #&ff
        STR     r6, [fp, #6*4]
        B       UpdatingJunkStringsOSFileExit

 [ Version >= 176
Read_BlockSize 
        ADR     r0, PassedFilename
        MOV     r2, #NULL
        addr    r3, anull
        ADR     r4, FullFilename
        MOV     r5, #0
        ADR     r6, SpecialField
        BL      TopPath_DoBusinessToPath
        SwiExit VS

        ; Does it exist?
        TEQ     r0, #object_nothing
        BEQ     JunkStringsNotFoundOSFileExit

        ; Is it a directory?
        TST     r0, #object_directory
        BNE     JunkStringsIsADirectoryOSFileExit

        LDR     r0, [fscb, #fscb_info]
        TST     r0, #fsinfo_multifsextensions
        addr    r0, ErrorBlock_UnsupportedFSEntry, EQ
        BLEQ    CopyError

        MOVVC   r0, #fsfile_ReadBlockSize
        BLVC    CallFSFile_Given

        ; Transfer r2 out of FileSwitch on success
        LDRVC   r2, fileblock_load
        STRVC   r2, [fp, #2*4]

        B       JunkStringsOSFileExit
 ]


LoadActionPrefix        DCB     "Alias$@LoadType_", 0
                        ALIGN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Now all the LoadFile ops

Load_UseNoLoadPath ; Try to load this file

        addr    r4, anull               ; Null path string

Load_UseGivenLoadPath ; Try to load along given path string

        MOV     r2, #NULL
        MOV     r3, r4
        B       DoTheLoad

Load_UseGivenLoadPathVar ; Try to load along given path variable

        MOV     r2, r4
        addr    r3, anull
        B       DoTheLoad

Load_UseLoadPath ; Try to load along File$Path

        addr    r2, FilePathVariableNameCR
        ADD     r3, r2, #(FilePathVariableDefault - FilePathVariableNameCR)

DoTheLoad

        ADR     r0, PassedFilename
        ADR     r4, FullFilename
        MOV     r5, #0
        ADR     r6, SpecialField
        BL      TopPath_DoBusinessToPath
        SwiExit VS

        TEQ     r0, #object_nothing
        BEQ     JunkStringsNotFoundOSFileExit
        TEQ     r0, #object_directory
        BEQ     JunkStringsIsADirectoryOSFileExit

        ; Leave access checking up to the individual filing system

        ; Store the file's info now, while we still have them
        LDRB    r14, [fp, #4*3]
        TEQ     r14, #0                 ; LSB of exec = 0 -> load at specified
        LDREQ   r14, [fp, #4*2]

        STR     r0, [fp, #0*4]
        ADD     r0, fp, #2*4
        STMIA   r0, {r2-r5}

        MOVEQ   r2, r14
        BEQ     Load_FileAtR2           ; else interpret 'load at own'

; ---------------- Suss how to load this file 'at own address' ----------------

 [ debugosfile
 DSTRING r1, "File to load at own address is "
 Push r1
 LDR r1, FullFilename
 DSTRING r1, ", fullfilename is "
 Pull r1
 DREG r2, "load is ",cc
 DREG r3, " and exec is "
 ]
        BL      IsFileTyped
 [ debugosfile
 BEQ %FT01
 DLINE "Loading file at load address"
01
 ]
        BNE     Load_FileAtR2

        MOV     r0, r2, ASR #8          ; File type now in the lowest 12 bits
        CMP     r0, #&FFFFFFF8          ; The only special file type for load
        MOVEQ   r2, #&8000              ; Which is always loaded at 32K
        BEQ     Load_FileAtR2           ; Type FF8

; .............................................................................

Load_UnrecognisedFile

        addr    r3, anull               ; Null postfix for 'l$t_nnn filename'
        addr    r4, LoadActionPrefix
        addr    r5, ErrorBlock_UnknownLoadAction
        BL      ReadActionVariable      ; Leaves r0 -> action vbl (pushed)
        BVS     JunkStringsOSFileExit

        SWI     XOS_CLI
        BLVS    CopyErrorExternal

        ADR     r0, ActionVariable
        BL      SFreeLinkedArea         ; Accumulate V

        B       LoadedFile

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; r2 = load address, r4 = file length

Load_FileAtR2

 [ debugosfile
 DSTRING r1, "Loading ",cc
 DREG r2, " at ",cc
 DREG r4, " length "
 ]
        ADD     r5, r2, r4              ; End address
        BL      ValidateR2R5_WriteToCore

        MOVVC   r3, r2
        LDRVC   r2, PassedFilename
        MOVVC   r0, #object_file
        BLVC    int_DoLoadFile


LoadedFile

        MOVVC   r0, #object_file        ; It was a file, your honour
                                        ; (There exist lying FS's eg. bbc#adfs)
        B       JunkStringsOSFileExit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Make error

; In    r2 = object type (&100 -> make 'dir not found' error)
;       r1 -> user's filename

MakeErrorOp
        MOV     r4, #space
        BL      strlenTS
        MOV     r0, #0
        TEQ     r2, #object_nothing + &100
        addr    r0, ErrorBlock_DirNotFound, EQ
        TEQ     r2, #object_nothing
        addr    r0, ErrorBlock_FileNotFound, EQ
        TEQ     r2, #object_file
        addr    r0, ErrorBlock_IsAFile, EQ
        TEQ     r2, #object_directory
        TEQNE   r2, #object_directory :OR: object_file
        addr    r0, ErrorBlock_IsADirectory, EQ
        TEQ     r0, #0
        BLNE    MagicCopyErrorSpan
        SwiExit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Set file type on file to that given

; In    r2 bottom 12 bits are file type to set
;       r1 -> allocated PassedFilename

StampSetTypeFileOp
 [ debugosfile
        DREG    r0, "Op=",cc
        DSTRING r1, " file ",cc
        DREG    r2, " having type set to "
 ]
        MOV     r8, r2

        ; Process the filename
        MOV     r7, r0
        ADR     r0, PassedFilename
        MOV     r2, #NULL
        addr    r3, anull
        ADR     r4, FullFilename
        MOV     r5, #0
        ADR     r6, SpecialField
        BL      TopPath_DoBusinessToPath
        SwiExit VS

        ; Does it exist?
        TEQ     r0, #object_nothing
        BEQ     JunkStringsNotFoundOSFileExit

        TEQ     r7, #OSFile_SetType
        BNE     %FT10

        ; SetType processing of the load and exec address
        BL      IsFileTyped
        BICEQ   r2, r2, #&000FF000
        BICEQ   r2, r2, #&00000F00
        ORREQ   r2, r2, r8, LSL #8
        MOVNE   r2, r8
        BLNE    SReadTime
        B       %FT20

10
        ; Stamp processing of the load and exec address
        BL      IsFileTyped
        MOVEQ   r2, r2, ASL #32-12-8
        MOVEQ   r2, r2, LSR #32-12
        LDRNE   r2, =&00000FFD
        BL      SReadTime

20
        MOV     r0, #fsfile_WriteInfo
        BL      CallFSFile_Given
        B       JunkStringsOSFileExit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    r2 bottom 12 bits are file type to set
;       r1 -> allocated PassedFilename

SaveCreateStampFileOp

        BL      SReadTime               ; Read machine date into r2,r3

        LDRB    r0, [fp, #4*0]          ; What was the original op (r0b) ?
        TEQ     r0, #OSFile_SaveStamp
        MOVEQ   r0, #fsfile_Save        ; Mutate the operation as appropriate
        BEQ     SaveFileOp
        MOVNE   r0, #fsfile_Create

; .............................................................................
; In    r0 = Op (Delete, Create, CreateDir)
;       r1 = Filename as supplied by user

DeleteCreateFileOp
        ; Save the parameters for a create
        Push    "r2,r3,r4,r5"

        ; Process the filename
        MOV     r7, r0
        ADR     r0, PassedFilename
        MOV     r2, #NULL
        addr    r3, anull
        ADR     r4, FullFilename
        TEQ     r7, #OSFile_Delete
        MOVEQ   r5, #TopPath_NoWildCards
        MOVNE   r5, #TopPath_NoMultiParts :OR: TopPath_NoWildCards
        ADR     r6, SpecialField
        BL      TopPath_DoBusinessToPath
        ADDVS   sp, sp, #4*4
        SwiExit VS

        ; Return the file's the parameters for delete op
        TEQ     r7, #OSFile_Delete
        BNE     %FT10

 [ debugosfile
        DLINE   "Delete..."
 ]
        ; Special handling for delete..

        ; Save old parameters for file
        MOV     r14, fp
        STMIA   r14!, {r0}
        STMIB   r14, {r2,r3,r4,r5}

 [ {FALSE}
 ; This code checks for partitions being empty before deleteing them.

        TEQ     r0, #object_file :OR: object_directory
        BNE     %FT10

 [ debugosfile
        DLINE   "Partition..."
 ]

        ; Special handling for deleting a directory
        Push    "r1,r6,fscb"
        SUB     sp, sp, #256
        BL      AssessDestinationForPathTailForDirRead
        MOV     r0, #fsfunc_ReadDirEntries
        MOV     r2, sp
        MOV     r3, #1
        MOV     r4, #0
        MOV     r5, #256
        BL      CallFSFunc_Given
        ADD     sp, sp, #256
        Pull    "r1,r6,fscb"
        BVS     %FT05
 [ debugosfile
        DREG    r3,"r3,r4=",cc
        DREG    r4,","
 ]
        CMP     r4, #-1
        CMPEQ   r3, #0
        LDRNE   r1, PassedFilename
        BLNE    SetMagicPartNotEmpty
05
        ADDVS   sp, sp, #4*4
        BVS     %FT80
 ]

10
        ; Restore the parameters for a create
        Pull    "r2,r3,r4,r5"

        ; If creating dir, then create as data stamped now
        TEQ     r7, #OSFile_CreateDir
        LDREQ   r2, =FileType_Data
        BLEQ    SReadTime

        BL      int_DeleteCreateFileOp

80
        B       JunkStringsOSFileExit


; .............................................................................
; In    r1 -> allocated PassedFilename

SaveFileOp
        Push    "r2,r3,r4,r5"

        ; Check the area of memory exists
        MOV     r2, r4
        BL      ValidateR2R5_ReadFromCore
        ADDVS   sp, sp, #4*4
        SwiExit VS

        ; Process the filename
        ADR     r0, PassedFilename
        MOV     r2, #NULL
        addr    r3, anull
        ADR     r4, FullFilename
        MOV     r5, #TopPath_NoMultiParts :OR: TopPath_NoWildCards
        ADR     r6, SpecialField
        BL      TopPath_DoBusinessToPath
        ADDVS   sp, sp, #4*4
        SwiExit VS

        Pull    "r2,r3,r4,r5"

        BL      int_DoSaveFile
        B       JunkStringsOSFileExit

UpdatingJunkStringsOSFileExit
        MOV     r14, fp
        STMIA   r14!, {r0}
        STMIB   r14, {r2,r3,r4,r5}

JunkStringsOSFileExit
        BL      JunkFileStrings
        SwiExit

JunkStringsNotFoundOSFileExit
        LDR     r1, PassedFilename
        BL      SetMagicFileNotFound
        B       JunkStringsOSFileExit

JunkStringsIsADirectoryOSFileExit
        LDR     r1, PassedFilename
        BL      SetMagicIsADirectory
        B       JunkStringsOSFileExit

; .............................................................................
; In    r1 -> user's filename

WriteInfoFileOp
        Push    "r2,r3,r5"

        ; Process the filename
        MOV     r7, r0
        ADR     r0, PassedFilename
        MOV     r2, #NULL
        addr    r3, anull
        ADR     r4, FullFilename
        MOV     r5, #0
        ADR     r6, SpecialField
        BL      TopPath_DoBusinessToPath
        ADDVS   sp, sp, #3*4
        SwiExit VS

        ; Check the object exists
        TEQ     r0, #object_nothing
        BNE     WriteInfoFilePresent

        ; If not there then generate error on non-alwaysopen filing systems
        ADD     sp, sp, #3*4
        LDR     lr, [fscb, #fscb_info]
        TST     lr, #fsinfo_alwaysopen
        BEQ     JunkStringsNotFoundOSFileExit
        B       JunkStringsOSFileExit

WriteInfoFilePresent
        ; The object exists - pick up the relevant parameters
        TEQ     r7, #OSFile_WriteInfo
        LDMEQIA sp, {r2,r3,r5}
        TEQ     r7, #OSFile_WriteLoad
        LDREQ   r2, [sp, #0*4]
        TEQ     r7, #OSFile_WriteExec
        LDREQ   r3, [sp, #1*4]
        TEQ     r7, #OSFile_WriteAttr
        LDREQ   r5, [sp, #2*4]
        ADD     sp, sp, #3*4
 [ debugosfile
        DREG    r7, "op=",cc
        DREG    r2, " L=",cc
        DREG    r3, " E=",cc
        DREG    r5, " A="
 ]

        ; Do WriteInfo whatever
;************** Horrendous kloodge to get round NetFS not being able to
; set the load and exec of a directory!
        LDRB    r14, [fscb, #fscb_info]
        TEQ     r14, #fsnumber_net
        MOVEQ   r0, r7
        MOVNE   r0, #OSFile_WriteInfo
        BL      CallFSFile_Given

        B       JunkStringsOSFileExit

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; JunkFileStrings
;
; In    -
;
; Out   r0 corrupt and SpecialField, FullFilename and PassedFilename freed
;
JunkFileStrings ENTRY "r0"
        ADR     r0, SpecialField
        BL      SFreeLinkedString
        ADR     r0, FullFilename
        BL      SFreeLinkedString
        ADR     r0, PassedFilename
        BL      SFreeLinkedString
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; int_DeleteCreateFileOp
;
; In    r0 = object type
;       r1 = tail of path to use
;       r2,r3,r4,r5
;               Create:    load, exec, start, end
;               CreateDir: load, exec, direntries, -
;               Delete:    load, exec, length, attributes from DoBusiness
;       r6 = pointer to special field/file handle to use
;       r7 = op
;       fscb^ set up
;       PassedFilename used for error generation
;
; Out   Op done
;
int_DeleteCreateFileOp ENTRY "r1,r6,fscb"
 [ debugosfile
 DREG r7, "Deletecreate op=",cc
 DSTRING r1, " on "
 ]
        ; Check if already deleted/there as appropriate
        TEQ     r7, #OSFile_Delete
        BNE     %FT10

        ; Are we trying to delete something which doesn't exist?
        TEQ     r0, #object_nothing
        BNE     %FT30
        EXIT

10
        ; Are we trying to create something which already exists?
        TEQ     r0, #object_nothing
        BEQ     %FT30
        TEQ     r7, #OSFile_Create
        BNE     %FT20

        ; Check create file - reject if a pure directory is there
        ; (09-09-93 was TST to catch partitions too, but this caused problems)
        TEQ     r0, #object_directory
        BNE     %FT30
        addr    r0, MagicErrorBlock_CreateFileOntoDir
        LDR     r1, PassedFilename
        BL      MagicCopyError
        EXIT
20
        ; Check create directory - reject if a pure file is there
        TEQ     r0, #object_file
        EXIT    NE
        addr    r0, MagicErrorBlock_CreateDirOntoFile
        LDR     r1, PassedFilename
        BL      MagicCopyError
        EXIT

30
        BL      TryGetFileClosed
        EXIT    VS

        ; Do the op
        MOV     r0, r7
        BL      CallFSFile_Given
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; int_DoLoadFile
;
; In    r0 = objecttype of file
;       r1 -> filename to pass to fs
;       r2 -> filename to use on error
;       r3 = address to load file to (already checked)
;       r4 = length of file
;       r6 = file handle/special field^
;       fscb^ set up
;
int_DoLoadFile ENTRY "r0,r1,r2,r3,r5,r7"
        BL      TryGetFileClosed
        EXIT    VS

 [ Use_fsfile_Load
        LDR     r14, [fscb, #fscb_info]
        TST     r14, #&ff
        BEQ     %FT10
        TST     r14, #fsinfo_dontuseload
        BNE     %FT10

        ; Load non-MultiFS file (traditional method)
        MOV     r0, #fsfile_Load
        MOV     r2, r3
        MOV     r3, #0
        BL      CallFSFile_Given
        EXIT

10
        ; Load MultiFS file
 ]
 [ debugosfile
        DLINE   "Doing Open etc to do load"
 ]

        ; Open it
        MOV     r5, #open_read
        MOV     r7, #open_read :OR: open_mustopen :OR: open_nodir
        BL      DoTheOpen_Common
        EXIT    VS
 [ debugosfile
        DREG    r0, "File opened on handle "
 ]

        ; GBPB the contents into memory
        MOV     r1, r0
        ADR     r14, gbpb_memadr
        STMIA   r14, {r3,r4}
        MOV     r0, #OSGBPB_ReadFromPTR
        Push    "r1"
        BL      Xfer_ReadBytes
        Pull    "r1"
        CLRV                            ; So V bit doesn't joggle the elbow of CloseThisFile
 [ debugosfile
        DREG    r1, "Bytes read, closing file "
 ]

        ; Close it, even if the GBPB gave an error
        BL      CloseThisFile
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; int_DoSaveFile
;
; In    r0 = Object type
;       r1 -> filename to pass to fs
;       r2 = load address
;       r3 = execute address
;       r4 = start
;       r5 = end
;       r6 = file handle/special field^
;       fscb^ set up
;       PassedFilename
;
int_DoSaveFile ENTRY "r0,r1,r2,r3,r5,r7,scb"
 [ debugosfile
        DREG    r0, "Saving over a ",cc
        DSTRING r1, " called ",cc
        DREG    r2, " using parameters ",cc
        DREG    r3, ",", cc
        DREG    r4, ",", cc
        DREG    r5, ",", cc
        DSTRING r6, " and special field "
 ]

        TEQ     fscb, #Nowt
        BLEQ    SetErrorNoSelectedFilingSystem
        EXIT    VS

 [ Use_fsfile_Save
 ; This section should be enabled to continue use of fsfile_Save
        LDR     r14, [fscb, #fscb_info]
        TST     r14, #&ff
        BEQ     %FT20
        TST     r14, #fsinfo_dontusesave
        BEQ     %FT20
 ]

        ; *save into a MultiFS area - do a create, openup, GBPB, Close sequence
        MOV     r7, #fsfile_Create
        BL      int_DeleteCreateFileOp

 [ debugosfile
        BVS     %FT01
        DLINE   "Created file without error"
        B       %FT02
01
        DLINE   "Created file with error"
02
 ]

        LDRVC   r2, PassedFilename
        MOVVC   r5, #open_update
        MOVVC   r7, #open_update :OR: open_mustopen :OR: open_nodir
        BLVC    DoTheOpen_Common
        EXIT    VS
        MOV     r1, r0

 [ debugosfile
        DREG    r1, "File open on handle "
 ]

        LDR     r5, [sp, #4*4]
        SUB     r5, r5, r4
        ADR     r14, gbpb_memadr
        STMIA   r14, {r4,r5}

 [ debugosfile
        DREG    r5, "Transfering ",cc
        DREG    r4, " bytes from "
 ]

        MOV     r0, #OSGBPB_WriteAtPTR
        Push    "r1"
        BL      Xfer_WriteBytes
        Pull    "r1"

        ; Drop scb_modified to prevent writing of stamp information
        BL      FindValidStream
        LDR     r14, scb_status
        BIC     r14, r14, #scb_modified
        STR     r14, scb_status
        BL      FlushAndCloseStream

        EXIT

 [ Use_fsfile_Save
 ; This section should be enabled to continue use of fsfile_Save
20
        TST     r0, #object_directory
        LDRNE   r1, PassedFilename
        addr    r0, MagicErrorBlock_CreateFileOntoDir, NE
        BLNE    MagicCopyError
        BLVC    TryGetFileClosed
        MOVVC   r0, #fsfile_Save
        BLVC    CallFSFile_Given

        EXIT
 ]

        LTORG

        END
